#ifndef __NET_GLOBAL_H__
#define __NET_GLOBAL_H__

#include <uuid/uuid.h>

#include "sdevent.h"
#include "sysy_lib.h"
#include "sysy_conf.h"

#define YNET_PORT_NULL ((uint32_t)-1)

#define YNET_NAME_UNKNOWN   "unknown"
#define BLOCK_LIST_PATH     SHM_ROOT"/blocklist"

typedef struct {
        int inited;
        int offline;
        uint32_t master_magic;
        nid_t local_nid;
        net_proto_t op;

        net_handle_t master;
        net_handle_t pasv_nh;
        char rack[MAX_NODEID_LEN];
        char name[MAX_NODEID_LEN];
        char home[MAX_PATH_LEN];
        uint32_t seq; /*local seq*/
        uint32_t port;
        int daemon;
        uint32_t uptime;
        uint32_t earliest_uptime;
        uint32_t admin_uptime;
        uint32_t xmitbuf;
        time_t info_time;
        uint64_t nid_sequence;
        char info_local[MAX_INFO_LEN];
} net_global_t;

/*init in net_lib.c*/

extern net_global_t ng;

static inline int net_isnull(const nid_t *nid)
{
        if (nid->id == 0)
                return 1;
        else
                return 0;
}

static inline const nid_t *net_getnid()
{
        /*
        if (net_isnull(&ng.local_nid))
                DBUG("nid is null\n");
        */

        //DINFO("nid : %u\n", ng.local_nid.id);
        return &ng.local_nid;
}

static inline void net_setnid(const nid_t *nid)
{
        YASSERT(nid->id >= 0);
        ng.local_nid = *nid;
}

static inline const nid_t *net_getadmin()
{
        YASSERT(ng.master.u.nid.id >= 0);
        return &ng.master.u.nid;
}

static inline int net_getadmin1(nid_t *nid)
{
        int ret;

        if (net_isnull(&ng.master.u.nid)) {
                ret = EAGAIN;
                GOTO(err_ret, ret);
        }

        YASSERT(nid->id > 0);
        *nid = ng.master.u.nid;

        return 0;
err_ret:
        return ret;
}

static inline void net_setadmin(const nid_t *nid)
{
        DINFO("set master as "NID_FORMAT"\n", NID_ARG(nid));

        YASSERT(nid->id > 0);
        id2nh(&ng.master, nid);
}

static inline int net_islocal(const nid_t *nid)
{
        if (net_isnull(nid))
                return 0;

        if (nid_cmp(nid, net_getnid()) == 0)
                return 1;
        else
                return 0;
}

#if ENABLE_LOCAL_RPC
static int  __enable_local_call__ = 0;
#else
static int  __enable_local_call__ = 1;
#endif

static inline int net_islocalcall(const nid_t *nid)
{
        return (net_islocal(nid) && __enable_local_call__);
}

static inline int net_blocked(const char *hostname)
{
        int ret, len;
        struct stat stbuf;
        char path[MAX_BUF_LEN], buf[MAX_BUF_LEN], *ptr;

        ptr = strrchr(hostname, '/');
        if (ptr == NULL) {
                snprintf(path, MAX_PATH_LEN, BLOCK_LIST_PATH"/%s", hostname);
        } else {
                len = ptr - hostname;
                memcpy(buf, hostname, len);
                buf[len] = '\0';
                snprintf(path, MAX_PATH_LEN, BLOCK_LIST_PATH"/%s", buf);
        }

        DBUG("path %s\n", path);

        ret = stat(path, &stbuf);
        if (ret == 0) {
                DWARN("%s is blocked\n", hostname);
                return 1;
        } else {
                return 0;
        }
}

#endif
